#ifndef     __WAIT_NOTIFY_MAP_H
#define     __WAIT_NOTIFY_MAP_H

#include "./cond_var.h"

namespace rtos {

template <typename K, typename V, uint32_t CAPACITY, uint32_t MAX_WAIT_TASK_SIZE, uint32_t FLAG_COND>
class WaitNotifyMap : private utils::NoCopyable {

public:
    struct Item {
        K key;
        V value;
    };

    void init() {
        m_mutex.init();
    }

    bool post(K key, V&& value) {
        m_mutex.lock();
        if (m_size >= CAPACITY) {
            m_mutex.un_lock();
            return false;
        }
        m_data[m_size].key = key;
        m_data[m_size].value = std::move(value);
        m_size += 1;
        m_cond.notify_all();
        m_mutex.lock();
        return true;
    }

    bool poll(K key, V& value, uint32_t timeout) {
        uint32_t time_count = 0;
        m_mutex.lock();
        for (;;) {
            uint32_t begin = osKernelGetTickCount();
            for (uint32_t i = 0; i < m_size; i ++) {
                if (m_data[i].key == key) {
                    value = std::move(m_data[i].value);
                    if (m_size > 1) {
                        m_data[i] = std::move(m_data[m_size - 1]);
                    }
                    m_size -= 1;
                    m_mutex.un_lock();
                    return true;
                }   
            }
            m_cond.wait( m_mutex, timeout );
            time_count += osKernelGetTickCount() - begin;
            if (time_count >= timeout) {
                break;
            }
        }
        m_mutex.un_lock();
        return false;
    }

private:
    Mutex m_mutex;
    CondVar<MAX_WAIT_TASK_SIZE, FLAG_COND> m_cond;
    Item m_data[CAPACITY];
    uint32_t m_size = 0;
};

}


#endif
